package com.school.sports.service.Impl;

import com.school.sports.dto.LoginRequest;
import com.school.sports.dto.LoginResponse;
import com.school.sports.entity.User;
import com.school.sports.exception.BusinessException;
import com.school.sports.mapper.UserMapper;
import com.school.sports.service.AuthService;
import com.school.sports.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;
import java.util.Map;
import java.util.HashMap;

/**
 * 认证服务实现类
 */
@Slf4j
@Service
public class AuthServiceImpl implements AuthService {

    private final AuthenticationManager authenticationManager;
    private final UserMapper userMapper;
    private final JwtUtil jwtUtil;
    private final RedisTemplate<String, Object> redisTemplate;
    private final PasswordEncoder passwordEncoder;

    // Redis key 前缀
    private static final String TOKEN_PREFIX = "auth:token:";
    private static final String BLACKLIST_PREFIX = "auth:blacklist:";

    public AuthServiceImpl(AuthenticationManager authenticationManager,
                         UserMapper userMapper,
                         JwtUtil jwtUtil,
                         RedisTemplate<String, Object> redisTemplate,
                         PasswordEncoder passwordEncoder) {
        this.authenticationManager = authenticationManager;
        this.userMapper = userMapper;
        this.jwtUtil = jwtUtil;
        this.redisTemplate = redisTemplate;
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    public LoginResponse login(LoginRequest loginRequest) {
        String username = loginRequest.getUsername();
        String password = loginRequest.getPassword();

        try {
            // 使用 Spring Security 进行身份验证
            Authentication authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(username, password)
            );

            // 获取认证后的用户信息
            User user = (User) authentication.getPrincipal();

            // 生成 JWT 令牌
            String token = jwtUtil.generateToken(username, user.getId(), user.getRoleName());

            // 将令牌存储到 Redis 中（可选，用于令牌管理）
            redisTemplate.opsForValue().set(
                    TOKEN_PREFIX + token,
                    user.getId(),
                    jwtUtil.getExpiration() / 1000,
                    TimeUnit.SECONDS
            );

            // 构建登录响应
            LoginResponse response = new LoginResponse();
            response.setUserId(user.getId());
            response.setUsername(user.getUsername());
            response.setRealName(user.getRealName());
            response.setRoleName(user.getRoleName());
            response.setRoleId(user.getRoleId());
            response.setToken(token);

            log.info("用户登录成功：{}", username);
            return response;

        } catch (AuthenticationException e) {
            log.warn("用户登录失败：{}", username);
            throw new BusinessException("用户名或密码错误");
        }
    }

    @Override
    public void logout(String token) {
        if (token != null && token.startsWith("Bearer ")) {
            token = token.substring(7);
        }

        if (jwtUtil.validateToken(token, jwtUtil.getUsernameFromToken(token))) {
            // 将令牌加入黑名单
            long expiration = jwtUtil.getExpirationDateFromToken(token).getTime() - System.currentTimeMillis();
            if (expiration > 0) {
                redisTemplate.opsForValue().set(
                        BLACKLIST_PREFIX + token,
                        "blacklisted",
                        expiration,
                        TimeUnit.MILLISECONDS
                );
            }

            // 删除活跃令牌
            redisTemplate.delete(TOKEN_PREFIX + token);

            log.info("用户登出成功");
        }
    }

    @Override
    public String refreshToken(String token) {
        if (token != null && token.startsWith("Bearer ")) {
            token = token.substring(7);
        }

        if (!jwtUtil.validateToken(token, jwtUtil.getUsernameFromToken(token))) {
            throw new BusinessException("令牌无效或已过期");
        }

        // 检查令牌是否在黑名单中
        if (Boolean.TRUE.equals(redisTemplate.hasKey(BLACKLIST_PREFIX + token))) {
            throw new BusinessException("令牌已失效");
        }

        // 删除旧令牌
        redisTemplate.delete(TOKEN_PREFIX + token);

        // 生成新令牌
        String username = jwtUtil.getUsernameFromToken(token);
        Long userId = jwtUtil.getUserIdFromToken(token);
        String role = jwtUtil.getRoleFromToken(token);
        String newToken = jwtUtil.generateToken(username, userId, role);

        // 存储新令牌
        redisTemplate.opsForValue().set(
                TOKEN_PREFIX + newToken,
                userId,
                jwtUtil.getExpiration() / 1000,
                TimeUnit.SECONDS
        );

        log.info("令牌刷新成功：{}", username);
        return newToken;
    }

    /**
     * 检查令牌是否在黑名单中
     */
    public boolean isTokenBlacklisted(String token) {
        return Boolean.TRUE.equals(redisTemplate.hasKey(BLACKLIST_PREFIX + token));
    }

    @Override
    public boolean checkUsernameExists(String username) {
        try {
            User user = userMapper.findByUsername(username);
            return user != null;
        } catch (Exception e) {
            log.error("检查用户名是否存在失败：{}", e.getMessage());
            throw new BusinessException("检查用户名失败");
        }
    }

    @Override
    public void register(Map<String, Object> registerData) {
        try {
            // 参数验证
            if (registerData == null || registerData.isEmpty()) {
                throw new BusinessException("注册数据不能为空");
            }

            String username = (String) registerData.get("username");
            String password = (String) registerData.get("password");
            String realName = (String) registerData.get("realName");
            String gender = (String) registerData.get("gender");
            String className = (String) registerData.get("className");
            String college = (String) registerData.get("college");
            String phone = (String) registerData.get("phone");
            String email = (String) registerData.get("email");

            // 必填字段验证
            if (username == null || username.trim().isEmpty()) {
                throw new BusinessException("用户名不能为空");
            }
            if (password == null || password.trim().isEmpty()) {
                throw new BusinessException("密码不能为空");
            }
            if (realName == null || realName.trim().isEmpty()) {
                throw new BusinessException("真实姓名不能为空");
            }

            // 用户名格式验证
            if (!username.matches("^[a-zA-Z0-9_]{3,20}$")) {
                throw new BusinessException("用户名只能包含字母、数字和下划线，长度3-20位");
            }

            // 密码强度验证
            if (password.length() < 6 || password.length() > 20) {
                throw new BusinessException("密码长度必须在6-20位之间");
            }

            // 邮箱格式验证
            if (email != null && !email.trim().isEmpty() && !email.matches("^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$")) {
                throw new BusinessException("邮箱格式不正确");
            }

            // 手机号格式验证
            if (phone != null && !phone.trim().isEmpty() && !phone.matches("^1[3-9]\\d{9}$")) {
                throw new BusinessException("手机号格式不正确");
            }

            // 检查用户名是否已存在
            if (checkUsernameExists(username)) {
                throw new BusinessException("用户名已存在");
            }

            // 创建新用户
            User newUser = new User();
            newUser.setUsername(username.trim());
            newUser.setPasswordHash(passwordEncoder.encode(password));
            newUser.setRealName(realName.trim());
            newUser.setGender(gender);
            newUser.setClassName(className);
            newUser.setCollege(college);
            newUser.setPhone(phone);
            newUser.setEmail(email);
            newUser.setRoleId(3); // 默认角色为学生
            newUser.setIsActive(true);

            userMapper.insert(newUser);
            log.info("用户注册成功：{}", username);

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("用户注册失败：{}", e.getMessage());
            throw new BusinessException("注册失败：" + e.getMessage());
        }
    }

    @Override
    public Map<String, Object> verifySecurityQuestion(Map<String, Object> verifyData) {
        try {
            String username = (String) verifyData.get("username");
            String question = (String) verifyData.get("question");
            String answer = (String) verifyData.get("answer");

            // 查找用户
            User user = userMapper.findByUsername(username);
            if (user == null) {
                throw new BusinessException("用户不存在");
            }

            // 简化实现：使用预设的安全问题和答案
            Map<String, String> presetSecurityAnswers = new HashMap<>();
            presetSecurityAnswers.put("admin", "校园运动会");
            presetSecurityAnswers.put("teacher1", "教学楼");
            presetSecurityAnswers.put("student1", "图书馆");
            presetSecurityAnswers.put("student2", "篮球场");
            presetSecurityAnswers.put("referee1", "操场");
            presetSecurityAnswers.put("volunteer1", "体育馆");

            String correctAnswer = presetSecurityAnswers.get(username);
            if (correctAnswer == null || !correctAnswer.equals(answer)) {
                throw new BusinessException("安全问题答案错误");
            }

            // 返回用户信息
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("username", user.getUsername());
            result.put("realName", user.getRealName());
            result.put("roleName", user.getRoleName());

            log.info("安全问题验证成功：{}", username);
            return result;

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("验证安全问题失败：{}", e.getMessage());
            throw new BusinessException("验证失败：" + e.getMessage());
        }
    }

    @Override
    public void resetPassword(Map<String, Object> resetData) {
        try {
            String username = (String) resetData.get("username");
            String newPassword = (String) resetData.get("newPassword");
            String securityAnswer = (String) resetData.get("securityAnswer");

            // 查找用户
            User user = userMapper.findByUsername(username);
            if (user == null) {
                throw new BusinessException("用户不存在");
            }

            // 验证安全问题答案
            Map<String, String> presetSecurityAnswers = new HashMap<>();
            presetSecurityAnswers.put("admin", "校园运动会");
            presetSecurityAnswers.put("teacher1", "教学楼");
            presetSecurityAnswers.put("student1", "图书馆");
            presetSecurityAnswers.put("student2", "篮球场");
            presetSecurityAnswers.put("referee1", "操场");
            presetSecurityAnswers.put("volunteer1", "体育馆");

            String correctAnswer = presetSecurityAnswers.get(username);
            if (correctAnswer == null || !correctAnswer.equals(securityAnswer)) {
                throw new BusinessException("安全问题答案错误");
            }

            // 更新密码
            user.setPasswordHash(passwordEncoder.encode(newPassword));
            userMapper.updateById(user);

            log.info("密码重置成功：{}", username);

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("密码重置失败：{}", e.getMessage());
            throw new BusinessException("重置失败：" + e.getMessage());
        }
    }
}